#include "pipe_elements.h"
#include "fdecode.h"
#include <string>
#include <iostream>
#include <stack>
using namespace std;
extern stack <int> rsremovelist;
extern int PC;
extern int debug;
extern map <int,bits> mMemory;
extern int cycle;
int pipeline::fetch()
{
    if(PC>=700)
        return 0;

    bits temp=mMemory[PC];
    if(temp.notop)
        return 0;
    if(debug)
        cout<<"\nFetching  Instruction ";temp.fprint();cout<<endl;
    temp.issuecycle=cycle;
    rIQ.push_back(temp,PC,cycle);
    if (temp.isjump)
    {
        if(rBTB.member(PC))
            PC=rBTB.getaddr(PC);
        else
        {
            rBTB.insert(PC,temp.gettarget());
            PC=PC+4;
        }
    }
    else
        PC=PC+4;

    return 1;
}
int pipeline::issue()
{
    int freerob;
    iQelement temp=rIQ.next(cycle);
    if(temp.cycle==0)
    {
        //delete (&temp);
        //        cout<<"Always with you\n";
        return 0;
    }
    freerob=rROB.freeid();
    if(freerob==-1)//no free slot in the rob
    {
        rIQ.push_front(temp);//stall
        return 0;
    }
    if(!temp.instruction.opcode.compare("NOP")||!temp.instruction.opcode.compare("BREAK"))
    {
        if(debug)
    cout<<"Issuing Instruction ";temp.instruction.fprint();cout<<endl;
        rROB.addat(freerob,temp,cycle,rRF);
        return 1;
    }
    int r=rRS.full();
    if(r==-1)
    {
           rIQ.push_front(temp);
        return 0;
    }
    if(debug)
    cout<<"Issuing Instruction ";temp.instruction.fprint();cout<<endl;
    rRS.issue(temp.instruction,cycle,freerob,r,rROB,rRF);
    rROB.addat(freerob,temp,cycle,rRF);
    

    return 1;
}
int pipeline::execute()
{
    rRS.execute(cycle,rCDB,rBTB,rROB,rIQ);
    return 1;

}
int pipeline::writeresult()
{
    CDBmember data;
    while(1)
    {
    data=rCDB.getnext(cycle);
    if(data.cycle==-1)
        break;
    //if(!data.optype.compare("SW"))
    //{
      //  cout<<"*******************"<<data.rsnumber<<endl;
    //}
    
    if(data.optype=="LW"&&data.loadcounter==1)
    {

        rROB.update(data,cycle,rCDB);
    }
    else
    {
        if(debug)
                cout<<"Writing result of "<<data.optype<<" ROB: "<<data.robid<<endl;
        rRS.update(data,data.robid,cycle);
        rROB.update(data,cycle,rCDB);
    }

    }
}
int pipeline::commit()
{
    rROB.commit(rRF,cycle);
    rROB.commit(rRF,cycle);
}